package by.cooker.persdic;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Properties;
import java.util.logging.Logger;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;

/**
 * @author cooker
 */
public class Window extends JFrame {
	private JLabel detailsLabel;

	private DefaultListModel listModel;
	private JList wordsList;

	private Dictionary dic;

	private Font guiFont;

	public Window() {
		super(PersDic.NAME + " " + PersDic.VERSION);
		initialize();
	}

	/**
	 * Method create buttons panel.
	 * 
	 * @return buttons panel.
	 */
	public JPanel getButtonsPanel() {
		JPanel buttonsPanel = new JPanel();
		buttonsPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
		buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.Y_AXIS));

		// add button
		JButton addButton = new JButton(new ImageIcon(getClass().getResource(
				"/by/cooker/persdic/images/add.png")));
		addButton.addActionListener(new AddAction());
		buttonsPanel.add(addButton);

		// separator
		buttonsPanel.add(Box.createRigidArea(new Dimension(0, 5)));

		// remove button
		JButton removeButton = new JButton(new ImageIcon(getClass()
				.getResource("/by/cooker/persdic/images/remove.png")));
		removeButton.addActionListener(new RemoveAction());
		buttonsPanel.add(removeButton);

		// separator
		buttonsPanel.add(Box.createRigidArea(new Dimension(0, 5)));

		// add button
		JButton importButton = new JButton(new ImageIcon(getClass()
				.getResource("/by/cooker/persdic/images/import.png")));
		importButton.addActionListener(new ImportAction());
		buttonsPanel.add(importButton);

		// separator
		buttonsPanel.add(Box.createRigidArea(new Dimension(0, 5)));

		// exoport button
		JButton exportButton = new JButton(new ImageIcon(getClass()
				.getResource("/by/cooker/persdic/images/export.png")));
		exportButton.addActionListener(new ExportAction());
		buttonsPanel.add(exportButton);

		// separator
		buttonsPanel.add(Box.createGlue());

		// help button
		JButton helpButton = new JButton(new ImageIcon(getClass().getResource(
				"/by/cooker/persdic/images/help.png")));
		helpButton.addActionListener(new HelpAction());
		buttonsPanel.add(helpButton);

		// separator
		buttonsPanel.add(Box.createRigidArea(new Dimension(0, 5)));

		// exit button
		JButton exitButton = new JButton(new ImageIcon(getClass().getResource(
				"/by/cooker/persdic/images/exit.png")));
		exitButton.addActionListener(new ExitAction());
		buttonsPanel.add(exitButton);
		return buttonsPanel;
	}

	public Dictionary createDictionary() {
		if (dic == null) {
			dic = new Dictionary();
		}
		return dic;
	}

	/**
	 * 
	 * @return
	 */
	public DefaultListModel getListModel() {
		listModel = (DefaultListModel) wordsList.getModel();
		return listModel;
	}

	/**
	 * Get words list.
	 * 
	 * @return words list.
	 */
	public JList getWordsList() {
		if (wordsList == null) {
			wordsList = new JList(new DefaultListModel()) {
				@Override
				public void paintComponent(Graphics g) {
					Graphics2D g2d = (Graphics2D) g;
					g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
							RenderingHints.VALUE_ANTIALIAS_ON);
					super.paintComponent(g);
				}
			};

			wordsList.setFont(getGUIFont());

			wordsList.addMouseListener(new MouseAdapter() {
				@Override
				public void mouseClicked(MouseEvent e) {
					if (e.getClickCount() == 2) {
						JList list = (JList) e.getSource();
						showDetails(list);
					}
				}
			});

			wordsList.addKeyListener(new KeyAdapter() {

				@Override
				public void keyPressed(KeyEvent e) {
					if (e.getKeyCode() == KeyEvent.VK_ENTER) {
						JList list = (JList) e.getSource();
						showDetails(list);
					}
				}
			});

		}

		return wordsList;
	}

	public void importDictionary() {

		JFileChooser chooser = new JFileChooser();
		chooser.showOpenDialog(Window.this);
		File database = chooser.getSelectedFile();
		if (database != null) {
			if (getListModel().size() > 0) {
				getListModel().removeAllElements();
			}

			if (dic.getAllWords().size() > 0) {
				dic.removeAllWords();
			}
			dic.importWordsDataBase(database);
		}

		fillWordsList();
	}

	/**
	 * Intialize.
	 */
	public void initialize() {
		createDictionary();
		JPanel left = new JPanel(new BorderLayout());
		JPanel right = new JPanel(new BorderLayout());

		left.add(new JScrollPane(getWordsList(),
				ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
				ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED),
				BorderLayout.CENTER);
		left.setBorder(BorderFactory.createEmptyBorder(5, 10, 10, 0));
		left.add(getSearchPanel(), BorderLayout.NORTH);

		add(left);

		right.add(getButtonsPanel(), BorderLayout.CENTER);
		add(right, BorderLayout.EAST);

		setSize(PersDic.getInteger("window.width"), PersDic
				.getInteger("window.height"));
	}

	/**
	 * Get GUI font.
	 * 
	 * @return font.
	 */
	public Font getGUIFont() {
		if (guiFont == null) {

			guiFont = new Font(PersDic.getString("font.name"), Font.PLAIN,
					PersDic.getInteger("font.size"));
		}
		return guiFont;
	}

	private static Logger l = Logger.getLogger("Window");

	public JPanel getSearchPanel() {
		JPanel panel = new JPanel(new BorderLayout());
		panel.setBorder(BorderFactory.createEmptyBorder(5, 1, 5, 0));

		final JTextField searchField = new JTextField();
		searchField.setFont(getGUIFont());

		panel.add(searchField);

		JButton searchButton = new JButton(new ImageIcon(getClass()
				.getResource("/by/cooker/persdic/images/search.png")));
		searchButton.setPreferredSize(new Dimension(25, 25));
		searchButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				String text = searchField.getText();
				if (getListModel().size() > 0 && text.length() > 0) {
					for (int i = 0; i < listModel.size(); i++) {
						if (text.equalsIgnoreCase((String) listModel.get(i))) {
							wordsList.setSelectedIndex(i);
						}
					}
				}

			}
		});
		panel.add(searchButton, BorderLayout.EAST);

		return panel;
	}

	/**
	 * 
	 * @return
	 */
	public JLabel getInformationLabel() {
		if (detailsLabel == null) {
			detailsLabel = new JLabel() {
				@Override
				public void paintComponent(Graphics g) {
					Graphics2D g2d = (Graphics2D) g;
					g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
							RenderingHints.VALUE_ANTIALIAS_ON);
					super.paintComponent(g);
				}
			};

			detailsLabel.setFont(getGUIFont());
		}
		return detailsLabel;
	}

	public void showDetails(JList list) {

		Word w = dic.getWord((String) list.getSelectedValue());

		StringBuilder info = new StringBuilder();
		info.append("<html>");
		info.append("<font size=\"10\">");
		info.append(w.getText());
		info.append("</font>");
		info.append("<br>");
		info.append("<fontsize=\"7\"><i>");
		info.append("[");
		info.append(w.getTranscription());
		info.append("]");
		info.append("</i></font>");
		info.append("<ol>");
		String[] t = w.getTranslate();
		for (String element : t) {
			info.append("<li>");
			info.append(element);
			info.append("</li>");
		}
		info.append("</ol>");
		info.append("</html>");
		getInformationLabel().setText(info.toString());
		JOptionPane.showMessageDialog(Window.this, getInformationLabel(),
				"Information", JOptionPane.INFORMATION_MESSAGE);
	}

	/**
	 * Save.
	 */
	public void exportDictionary() {
		JFileChooser chooser = new JFileChooser();
		chooser.showSaveDialog(Window.this);
		File database = chooser.getSelectedFile();
		if (database != null) {
			dic.exportWordsDataBase(database);
		}
	}

	/**
	 * Fill.
	 */
	public void fillWordsList() {
		ArrayList<Word> words = dic.getAllWords();
		for (Word word : words) {
			listModel.addElement(word.getText());
		}
	}

	private class HelpAction extends AbstractAction {
		private JLabel help;

		@Override
		public void actionPerformed(ActionEvent e) {
			JOptionPane.showMessageDialog(Window.this, getHelpLabel());
		}

		/**
		 * Get help label.
		 * 
		 * @return label.
		 */
		private JLabel getHelpLabel() {
			if (help == null) {
				help = new JLabel() {

					@Override
					public void paintComponent(Graphics g) {
						Graphics2D g2d = (Graphics2D) g;
						g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
								RenderingHints.VALUE_ANTIALIAS_ON);
						super.paintComponent(g);
					}
				};
				help
						.setText("<html>"
								+ "<font size=\"5\">PersonalDictionary 0.1</font><br>"
								+ "Very simple cross-platform personal dictionary<br>"
								+ "for record words writen in Java.<br>"
								+ "Copyright(C) 2009 cooker<br>"
								+ "Homepage: <a href=\"\">http://code.google.com/p/persdic/</a>"
								+ "</html>");
				help.setFont(getGUIFont());
			}
			return help;
		}

	}

	private class ExportAction extends AbstractAction {
		@Override
		public void actionPerformed(ActionEvent e) {
			exportDictionary();
		}
	}

	private class ImportAction extends AbstractAction {
		@Override
		public void actionPerformed(ActionEvent e) {
			importDictionary();
		}
	}

	private class RemoveAction extends AbstractAction {
		@Override
		public void actionPerformed(ActionEvent e) {
			if (!wordsList.isSelectionEmpty()) {
				String word = (String) wordsList.getSelectedValue();
				dic.removeWord(word);
				listModel.removeElement(word);
			}
		}
	}

	private class AddAction extends AbstractAction {
		private JTextField wordField;
		private JTextField transcriptionField;
		private JTextField translateField;

		@Override
		public void actionPerformed(ActionEvent e) {
			JPanel panel = getAddWordPanel();
			int action = JOptionPane.showConfirmDialog(Window.this, panel,
					"New Word.", JOptionPane.OK_CANCEL_OPTION);

			if (action == JOptionPane.CANCEL_OPTION) {
				return;
			} else if (action == JOptionPane.OK_OPTION) {
				String word = wordField.getText();
				String transcription = transcriptionField.getText();
				String translate = translateField.getText();

				if (word == null || word.length() == 0 || transcription == null
						|| transcription.length() == 0 || translate == null
						|| translate.length() == 0) {
					return;
				} else {
					Word w = new Word(getListModel().getSize(), word,
							transcription, translate.split(" "));
					dic.addWord(w);
					listModel.addElement(w.getText());

					wordField.setText(null);
					transcriptionField.setText(null);
					translateField.setText(null);
				}
			}
		}

		/**
		 * Method create panel wich controls for add new word.
		 * 
		 * @return panel.
		 */
		private JPanel getAddWordPanel() {
			JPanel addWordPanel = new JPanel();
			addWordPanel.setLayout(new GridLayout(3, 2));

			wordField = new JTextField();
			wordField.setFont(getGUIFont());
			addWordPanel.add(getLabel("Word"), BorderLayout.WEST);
			addWordPanel.add(wordField);

			transcriptionField = new JTextField();
			transcriptionField.setFont(getGUIFont());
			addWordPanel.add(getLabel("Transcription: "), BorderLayout.WEST);
			addWordPanel.add(transcriptionField);

			translateField = new JTextField();
			translateField.setFont(getGUIFont());
			addWordPanel.add(getLabel("Translate: "), BorderLayout.WEST);
			addWordPanel.add(translateField);

			return addWordPanel;
		}

		/**
		 * Create label.
		 * 
		 * @param title
		 *            title fot label.
		 * @return label.
		 */
		private JLabel getLabel(String title) {
			JLabel label = new JLabel(title) {
				@Override
				public void paintComponent(Graphics g) {
					Graphics2D g2d = (Graphics2D) g;
					g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
							RenderingHints.VALUE_ANTIALIAS_ON);
					super.paintComponent(g);
				}
			};
			label.setText(title);
			label.setFont(getGUIFont());
			return label;
		}
	}

	private class ExitAction extends AbstractAction {
		@Override
		public void actionPerformed(ActionEvent e) {
			exit();
		}

		/**
		 * Exit.
		 */
		private void exit() {
			Window.this.dispose();
			System.exit(0);
		}
	}
}
